package com.essence.grabiec104.grab.dao;

import com.essence.common.model.BytesFrame;
import com.essence.common.model.Point;
import com.essence.common.model.Substation;
import com.essence.grabiec104.grab.model.AlarmRecord;
import com.essence.grabiec104.grab.model.AlarmRule;
import com.essence.grabiec104.grab.model.AlarmRuleQuery;
import com.essence.grabiec104.grab.model.CorrelationPointQuery;
import com.essence.grabiec104.grab.model.PointInfo;
import com.essence.grabiec104.grab.model.query.PointCountQuery;
import com.essence.grabiec104.grab.model.query.PointInfoQuery;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import zmq.socket.pubsub.Sub;

import java.util.List;
import java.util.Map;

@Mapper
public interface AlarmDao {
    List<AlarmRule> selectAllAlarmRule();

    List<Substation> getAllSubstation();

    Substation getSubstationByHostAndPort(@Param("host") String host, @Param("port") int port);

    Substation getSubstationById(@Param("id") long id);

    int addSubstation(@Param("substation") Substation substation);

    int updateSubstation(@Param("substation") Substation substation);

    int deleteSubstation(@Param("substation") Substation substation);

    int deleteAlarmRuleByStateId(@Param("id") long stateId);

    int deleteAllAlarmRules();

    int addAlarmRules(@Param("alarmRules") List<AlarmRuleQuery> alarmRules);

    List<AlarmRuleQuery> selectAlarmRulesByStateId(@Param("id") long stateId);

    int updateStationInfoScanFlag(@Param("host") String host, @Param("flag") long scanFlag);

    int insertAlarm(@Param("ar") AlarmRecord alarmRecord);

    int updateAlarm(@Param("ar") AlarmRecord alarmRecord);

    int updateAlarmById(@Param("ar") AlarmRecord alarmRecord);

    // 判断该站是否正在告警
    int countAlarm(@Param("ar") AlarmRecord alarmRecord);

    List<AlarmRecord> selectAlarmRecord(@Param("limit") int limit, @Param("offset") int offset);

    AlarmRecord selectAlarmRecordById(@Param("id") long id);

    List<AlarmRecord> selectAlarmRecordBySubstationIdAndMetricType(@Param("substationId") long substationId, @Param("metricType") int metricType, @Param("status") int status);

    int closeAlarmRecordById(@Param("id") long id);

    String getRtuNameByIpAndPort(@Param("ip") String ip, @Param("port") int port);

    int deletePoint(@Param("point") Point point);

    List<Point> selectPointBySubstationId(@Param("substationId") long substationId);

    int deletePointBySubstationId(@Param("substationId") long substationId);

    void emptyPoint();

    List<Point> selectAllPoint();

    void emptyPointRelation();

    int insertPointRelation(@Param("query") CorrelationPointQuery correlationPointQuery);

    List<BytesFrame> selectControlFrameBySubstationId(@Param("host") String host, @Param("timestamp") long timestamp);

    /**
     * 将所有告警规则的enabled置为false
     *
     * @return 更新的记录数
     */
    int disableAllAlarmRules();

    /**
     * 根据条件更新告警规则
     *
     * @param alarmRule 告警规则
     * @return 更新的记录数
     */
    int updateAlarmRuleByCondition(@Param("alarmRule") AlarmRuleQuery alarmRule);

    /**
     * 根据条件查询告警规则
     *
     * @param alarmRule 告警规则
     * @return 告警规则
     */
    AlarmRuleQuery selectAlarmRuleByCondition(@Param("alarmRule") AlarmRuleQuery alarmRule);

    /**
     * 删除告警记录
     *
     * @param ruleIds 规则ID列表
     * @return 删除的记录数
     */
    int deleteAlarmRecordsByRuleIds(@Param("ruleIds") List<Long> ruleIds);

    /**
     * 删除告警规则
     *
     * @param ruleIds 规则ID列表
     * @return 删除的记录数
     */
    int deleteAlarmRulesByIds(@Param("ruleIds") List<Long> ruleIds);

    /**
     * 查询所有enabled为false的告警规则ID
     *
     * @return 规则ID列表
     */
    List<Long> selectDisabledAlarmRuleIds();

    /**
     * 统计指定时间范围内的控制帧总数
     *
     * @param substationId 站ID
     * @param startTime    开始时间
     * @return 控制帧总数
     */
    int countControlFramesInTimeRange(@Param("substationId") long substationId,
                                      @Param("startTime") long startTime);

    /**
     * 更新站的scan_flag
     *
     * @param substationId 站ID
     * @param scanFlag     扫描标志
     * @return 更新的记录数
     */
    int updateSubstationScanFlag(@Param("substationId") long substationId,
                                 @Param("scanFlag") long scanFlag);

    /**
     * 统计指定时间范围内的控制点总数
     *
     * @param substationId 站ID
     * @param startTime    开始时间
     * @return 控制点总数
     */
    int countControlPointsInTimeRange(@Param("substationId") long substationId,
                                      @Param("startTime") long startTime);

    /**
     * 统计指定时间范围内每个遥控点的操作次数
     *
     * @param substationId 站ID
     * @param startTime    开始时间
     * @return 遥控点操作次数列表，包含点地址和操作次数
     */
    List<PointCountQuery> countYkPointOperationsInTimeRange(@Param("substationId") long substationId,
                                                            @Param("startTime") long startTime);

    /**
     * 统计指定时间范围内每个遥调点的操作次数
     *
     * @param substationId 站ID
     * @param startTime    开始时间
     * @return 遥控点操作次数列表，包含点地址和操作次数
     */
    List<PointCountQuery> countSdPointOperationsInTimeRange(@Param("substationId") long substationId,
                                                            @Param("startTime") long startTime);

    /**
     * 根据规则ID、站点ID和点ID查询告警记录
     *
     * @param ruleId       规则ID
     * @param substationId 站点ID
     * @param pointId      点ID
     * @return 告警记录
     */
    AlarmRecord selectOpeningAlarmRecord(@Param("ruleId") long ruleId,
                                         @Param("substationId") long substationId,
                                         @Param("pointId") long pointId);

    /**
     * 根据规则ID、站点ID和点ID查询告警记录
     *
     * @param ruleId       规则ID
     * @param substationId 站点ID
     * @return 告警记录
     */
    List<AlarmRecord> selectOpeningAlarmRecords(@Param("ruleId") long ruleId,
                                                @Param("substationId") long substationId);

    /**
     * 查询指定时间范围内的遥调点信息
     *
     * @param startTime    开始时间戳
     * @param endTime      结束时间戳
     * @param substationId 站ID
     * @return 遥调点信息列表
     */
    List<PointInfo> selectYtPointInfoInTimeRange(@Param("substationId") long substationId, @Param("startTime") long startTime, @Param("endTime") long endTime);

    /**
     * 查询指定时刻之后的遥调点信息
     *
     * @param substationId 站ID
     * @param start        开始TIMESTAMP
     * @param pointType    点类型
     * @param direction    方向 'Downstream' OR 'Upstream'
     * @return 遥调点信息列表
     */
    List<PointInfoQuery> selectPointInfoSinceTime(@Param("substationId") long substationId,
                                                  @Param("start") long start,
                                                  @Param("direction") String direction,
                                                  @Param("pointType") int pointType);

    /**
     * 查询指定时间范围内指定点号的最后一条数据
     *
     * @param pointAddress 点号地址
     * @param startTime    开始时间戳
     * @param endTime      结束时间戳
     * @return 点信息
     */
    PointInfo selectLastPointInfoByAddressAndTimeRange(@Param("pointAddress") int pointAddress,
                                                       @Param("startTime") long startTime,
                                                       @Param("endTime") long endTime);

    int checkAlarmRuleByPacketIdAndRuleId(@Param("packetId") long packetId, @Param("ruleId") long ruleId);

    List<PointInfo> selectFirstYcPointInfoBySubstationIdAndTimeRange(@Param("substationId") long substationId, @Param("startTime") long startTime);

    List<PointInfo> selectLastYcPointInfoBySubstationIdAndTimeRange(@Param("substationId") long substationId, @Param("startTime") long startTime);

    int sumAlarmRecord();

    int sumAlarmRecordByCycle(@Param("startTime") long startTime, @Param("endTime") long endTime);
}
